﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HanoiSimulator
{
    public partial class PlayForm : Form
    {
        int FloorCount;
        int count;
        private Point mouse_offset;
        Stack<Button> towerA, towerB, towerC;
        StepHelper sh;

        public PlayForm()
        {
            InitializeComponent();
            try
            {
                InitForm initForm = new InitForm();
                initForm.ShowDialog();
                FloorCount = initForm.GetFloorCount();
                towerA = new Stack<Button>();
                towerB = new Stack<Button>();
                towerC = new Stack<Button>();
                int maxWidth = pnlA.Width - 20;
                int maxFloor = (int)((pnlA.Height - 10) / 30);
                if (FloorCount > maxFloor)
                {
                    throw new Exception("层数超过限制。");
                }
                for (int i = FloorCount; i > 0; i--)
                {
                    Button btn = new Button();
                    btn.Name = "btn" + i;
                    btn.Text = (i).ToString();
                    int btnWidth = maxWidth - (FloorCount - i) * 10;
                    int btnLocationY = pnlA.Height - (FloorCount - i + 1) * 30;
                    int btnLocationX = (pnlA.Width - btnWidth) / 2;
                    btn.BackColor = Color.Salmon;
                    btn.ForeColor = Color.White;
                    btn.Location = new Point(btnLocationX, btnLocationY);
                    btn.Size = new Size(btnWidth, 25);
                    btn.MouseDown += this.MouseDownHandler;
                    btn.MouseUp += this.MouseUpHandler;
                    towerA.Push(btn);
                }
                FlushUI();
            }
            catch (Exception err)
            {
                MessageBox.Show("发生异常。错误的详细信息：" + err.Message);
            }
        }

        private void PlayForm_Load(object sender, EventArgs e)
        {
            sh = new StepHelper(FloorCount);
            sh.Show();
        }

        private void FlushUI()
        {
            pnlA.Controls.Clear();
            pnlB.Controls.Clear();
            pnlC.Controls.Clear();
            int maxWidth = pnlA.Width - 20;
            Button[] towerAArray = towerA.ToArray();
            Button[] towerBArray = towerB.ToArray();
            Button[] towerCArray = towerC.ToArray();
            for (int i = towerA.Count; i > 0; i--)
            {
                Button btn = towerAArray[i - 1];
                int btnLocationY = pnlA.Height - (towerA.Count - i + 1) * 30;
                int btnLocationX = (pnlA.Width - btn.Width) / 2;
                btn.Location = new Point(btnLocationX, btnLocationY);
                pnlA.Controls.Add(btn);
            }
            for (int i = towerB.Count; i > 0; i--)
            {
                Button btn = towerBArray[i - 1];
                int btnLocationY = pnlB.Height - (towerB.Count - i + 1) * 30;
                int btnLocationX = (pnlB.Width - btn.Width) / 2;
                btn.Location = new Point(btnLocationX, btnLocationY);
                pnlB.Controls.Add(btn);
            }
            for (int i = towerC.Count; i > 0; i--)
            {
                Button btn = towerCArray[i - 1];
                int btnLocationY = pnlC.Height - (towerC.Count - i + 1) * 30;
                int btnLocationX = (pnlC.Width - btn.Width) / 2;
                btn.Location = new Point(btnLocationX, btnLocationY);
                pnlC.Controls.Add(btn);
            }
            lblCount.Text = "计数： " + count.ToString();
        }

        private void MouseDownHandler(object sender, MouseEventArgs e)
        {
            mouse_offset = new Point(-e.X, -e.Y);
        }

        private void MouseUpHandler(object senderObj, MouseEventArgs e)
        {
            try
            {
                if (e.Button == MouseButtons.Left)
                {
                    Button sender = senderObj as Button;
                    Panel origonPanel = sender.Parent as Panel;
                    Point presentMousePos = Control.MousePosition;
                    presentMousePos.Offset(NegatePoint(this.Location));
                    Panel targetPanel = this.GetChildAtPoint(presentMousePos) as Panel;
                    if (origonPanel == null || targetPanel == null || sender == null)
                        throw new Exception("无法定位目标。目标为null。");
                    Button btn;
                    switch (origonPanel.Name)
                    {
                        case "pnlA":
                            btn = towerA.Peek();
                            towerA.Pop();
                            break;
                        case "pnlB":
                            btn = towerB.Peek();
                            towerB.Pop();
                            break;
                        case "pnlC":
                            btn = towerC.Peek();
                            towerC.Pop();
                            break;
                        default:
                            throw new Exception("无法定位目标。");
                    }
                    switch (targetPanel.Name)
                    {
                        case "pnlA":
                            towerA.Push(btn);
                            break;
                        case "pnlB":
                            towerB.Push(btn);
                            break;
                        case "pnlC":
                            towerC.Push(btn);
                            break;
                        default:
                            throw new Exception("无法定位目标。");
                    }
                    count++;
                    FlushUI();
                    sh.NextStep();
                }
            }
            catch(Exception err)
            {
                MessageBox.Show("发生异常。错误的详细信息：" + err.Message);
            }
        }
        
        private Point CopyPoint(Point op)
        {
            return new Point(op.X, op.Y);
        }

        private Point NegatePoint(Point op)
        {
            return new Point(-op.X, -op.Y);
        }
    }
}